#pragma once

#include "Thread.hpp"
#include "Mutex.hpp"
#include "logMessage.hpp"
#include <queue>//盛放任务的载体
#include <vector>//用于盛放线程的载体
#include <mutex>

static const int gtdnum = 5;

template<class T>
class ThreadPool;

template<class T>
class ThreadData
{
public:
    ThreadData(ThreadPool<T>* this_, std::string name_)
    :_this(this_), _name(name_)
    {}
public:
    ThreadPool<T>* _this;
    std::string _name;
};

template<class T>
class ThreadPool
{
private:
    static void* handler(void* args)//静态成员函数无法访问动态成员变量，所以需要另一个类来保存
    {
        ThreadData<T>* td = static_cast<ThreadData<T>*> (args);
        while(true)
        {
            td->_this->queue_lock();
            while(td->_this->task_empty()) 
            {
                td->_this->thread_wait();
            }
            T t = td->_this->pop();
            td->_this->queue_unlock();
            t();
        }
        delete td;
        return nullptr;
    }
private:
    void queue_lock()
    {
        pthread_mutex_lock(&_mutex);
    }
    void queue_unlock()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void thread_wait()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    bool task_empty()
    {
        return _task_queue.empty();
    }
    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }
private:
    ThreadPool(int thread_num = gtdnum):_thread_num(thread_num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        for(int i = 0; i < _thread_num; i++)
        {
            _thread_pool.push_back(new Thread());
        }
    }
public:
    void run()
    {
        for(auto &it :_thread_pool)
        {
            ThreadData<T>* td = new ThreadData<T>(this, it->getname());

            logMessage(NORMAL, "%s run......", it->getname().c_str());
            // std::cout << it->getname() << " run......" << std::endl;
            it->start(handler, td);
        }
    }
    void push(const T& task)
    {
        LockGaurd lkg(&_mutex);
        pthread_cond_signal(&_cond);
        _task_queue.push(task);
    }
    
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for(auto &it :_thread_pool)
        {
            delete it;
        }
    }

    ThreadPool(const ThreadPool<T>&) = delete;//拷贝构造不允许
    void operator =(const ThreadPool<T> & td) = delete;//在单例模式中，赋值操作不允许
public:
    static ThreadPool<T>* getInstance()
    {
        if(tp == nullptr)
        {
            std::mutex mtx;
            mtx.lock();
            if(tp == nullptr)
            {
                tp = new ThreadPool<T>();
            }
            mtx.unlock();
        }
        return tp;
    }
private:
    std::vector<Thread*> _thread_pool;//线程池
    std::queue<T> _task_queue;//任务队列
    pthread_mutex_t _mutex;//互斥锁
    pthread_cond_t _cond;//条件变量
    int _thread_num;//线程最大数量
private:
    static ThreadPool<T>* tp;
};

template<class T>
ThreadPool<T>* ThreadPool<T>::tp = nullptr;